//
//  TranslationManager.swift
//  GLUZSwift
//
//  Created by xyanl on 2025/3/29.
//
//  翻译
import UIKit
import ZegoExpressEngine

class TranslationManager: NSObject {

    var fromLanguage: String = ""
    var toLanguage: String = ""
    var realtimeTranslationBlock: ((IMRecvSeiModel) -> Void)?
    
    static let shared: TranslationManager = TranslationManager()
    
    private var atManager: AudioTranscriptionManager?
    
}

extension TranslationManager {
    
    /// 开始音频采集
    func startAudioDataObserver() {
        // 需要的音频数据类型 Bitmask，此处示例四个回调都开启
        let bitmask: ZegoAudioDataCallbackBitMask = [.captured, .player]
        // 需要的音频数据参数，此处示例单声道、16 K
        let param = ZegoAudioFrameParam()
        param.channel = .mono
        param.sampleRate = .rate16K
        
        // 开启获取原始音频数据功能
        ZegoExpressEngine.shared().startAudioDataObserver(bitmask, param: param)
        // 设置音频数据回调
        ZegoExpressEngine.shared().setAudioDataHandler(self)
        
    }
    
    /// 开启事件监听
    func startEventHandler() {
        ZegoExpressEngine.shared().setEventHandler(self)
    }
    
    /// 停止音频采集
    func stopAudioDataObserver() {
        // 异步停止，避免阻塞调用线程
        DispatchQueue.global(qos: .userInitiated).async {
            ZegoExpressEngine.shared().stopAudioDataObserver()
        }
    }
    
    /// 开始实时翻译
    func startRealtimeTranslation() {
        stopRealtimeTranslation()
        atManager = AudioTranscriptionManager()
        atManager!.fromLanguage = fromLanguage
        atManager!.toLanguage = toLanguage
        atManager!.delegate = self
        // Thread running at User-initiated quality-of-service class waiting on a lower QoS thread running at Default quality-of-service class. Investigate ways to avoid priority inversions
        // 以用户发起的服务质量类运行的线程正在等待以默认服务质量类运行的较低QoS的线程。研究避免优先级反转的方法
        // 之前使用的defalt，会出现上面的提示，DISPATCH_QUEUE_PRIORITY_DEFAULT 前面正运行着一个低的 QoS 线程，可能造成优先级反转，换成 DISPATCH_QUEUE_PRIORITY_LOW 就不会出现警告了
        /**
         DISPATCH_QUEUE_PRIORITY_HIGH:        .userInteractive
         DISPATCH_QUEUE_PRIORITY_DEFAULT:      .default
         DISPATCH_QUEUE_PRIORITY_LOW:          .utility
         DISPATCH_QUEUE_PRIORITY_BACKGROUND:  .background
         */
        DispatchQueue.global(qos: .utility).async { [weak self] in
            /// 异步线程
            // 需要放到线程中，否则链接不上
            self?.atManager!.connectWebSocket()
        }
        
    }
    
    /// 停止实时翻译
    func stopRealtimeTranslation() {
        if atManager != nil {
            atManager!.closeWebSocket()
            atManager = nil
        }
    }
    
    // 发送SEI 消息
    func sendSEIMessage(_ msg: String) {
        guard let data = msg.toData else { return }
        ZegoExpressEngine.shared().sendSEI(data)
    }
}

// MARK: - AudioTranscriptionDelegate
extension TranslationManager: AudioTranscriptionDelegate {
    func onRecognizedText(text: String, translatedText: String) {
        MTManager.translation(from: fromLanguage, to: toLanguage, text: text) { src, dst in
            DispatchQueue.main.async {
                let model = IMRecvSeiModel()
                model.type = "1"
                model.trans = dst
                model.text = "\(text)(\(dst))"
                model.userId = String(UserProfile.userId)
                model.username = UserProfile.username
                model.usernameRu = UserProfile.usernameRu
                self.realtimeTranslationBlock?(model)
            }
        } failure: { error in
            xLog("翻译失败，\(error.debugDescription)")
        }
    }
    
    func didClose(code: Int, reason: String) {
        xLog("音频转写关闭")
    }
    
}

// MARK: - ZegoAudioDataHandler
extension TranslationManager: ZegoAudioDataHandler {
    func onCapturedAudioData(_ data: UnsafePointer<UInt8>, dataLength: UInt32, param: ZegoAudioFrameParam) {
        // 本地采集音频数据，推流后可收到回调
        let sendData = Data(bytes: data, count: Int(dataLength))
        // 实时转写
        atManager?.sendAudioData(data: sendData)
    }
}

extension TranslationManager: ZegoEventHandler {
    func onPlayerSyncRecvSEI(_ data: Data, streamID: String) {
        if let jsonString = data.toString {
            xLog("接收 sei \(jsonString)")
            if let model = JsonUtil.modelFromJsonString(jsonString, IMRecvSeiModel.self) {
                realtimeTranslationBlock?(model)
            }
        }
    }
}
